/* $RCSFile: Update.aspx.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice/Setup/Update.aspx.cs $
 * $log$
 * Revision 27 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 27 2011/02/22 01:22:09  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 20 2010/08/09 10:51:22  christian.surieux
 *   Added Log comment to all .aspx .ascx .master files
 * Revision 19 2010/08/09 09:44:01  christian.surieux
 *   Added Log to cs sources files
 * Revision 6 2010/08/06 19:56:26  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Globalization;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Web;
using System.Web.Configuration;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.IO;
using System.Web.Security;

using AddonNice.Configuration;
using AddonNice.Settings;
using AddonNice.Helpers;
using AddonNice.Security;
using AddonNice.Authentication;
using AddonNice.Diagnostics;
using AddonNice.Core;
using AddonNice.CRMWrapper;
using AddonNice.UI.WebControls;

using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;
using Path2     =   AddonNice.Settings.Path;

namespace AddonNice.Setup
{
	/// <summary>
	/// This page manage update for AddonNice 
	/// It uses scripts in the setup/scrpits folder to raise database version to code version
	/// </summary>
	public partial class Update : Page
	{
    
        #region Internal utility class

        [Serializable]
		private class UpdateEntry : IComparable 
		{
			/// <summary>
			/// IComparable.CompareTo implementation.
			/// </summary>
			public int CompareTo(object obj) 
			{
				if(obj is UpdateEntry) 
				{
					UpdateEntry upd = (UpdateEntry) obj;
					if (VersionNumber.CompareTo(upd.VersionNumber) == 0) //Version numbers are equal
						return Version.CompareTo(upd.Version);
					return VersionNumber.CompareTo(upd.VersionNumber);
				}
				throw new ArgumentException("Update: object is not a UpdateEntry");    
			}

			public int VersionNumber				=   0;
			public string Version					=   string.Empty;
			public DateTime Date;
			public ArrayList SqlScripts				=   new ArrayList();
			public ArrayList Transacs				=   new ArrayList();
			public ArrayList Modules				=   new ArrayList();
			public bool UseTransaction				=   true;
			public bool Apply						=   false;
		}
        
        #endregion Internal utility class

        #region properties 

        /// <summary>
        /// Beware that wrapper is not loaded when setup is called: we have not loaded portalsettings and not installed a wrapper
        /// </summary>
        CRMWrapperBase Wrapper                      =   null;

        #region progress Management

        /// <summary>
        /// current position in setup
        /// </summary>
        int installCount               =   0;
        /// <summary>
        /// One step for each script and each module to install
        /// </summary>
        int totalSteps              
        {
            get
            {
                object ob = ViewState["totalSteps"];
                if (ob != null)
                    return (int)ob;
                return 0;
            }
            set
            {
                ViewState["totalSteps"] =   value;
            }
        }
        
        #endregion progress Management

        private UpdateEntry[] scriptsList
        {
            get
            {
                object ob = ViewState["SetupscriptsList"];
                if (ob != null)
                    return (UpdateEntry[])ob;
                return null;
            }
            set
            {
                ViewState["SetupscriptsList"] =   value;
            }
        }

        int dbVersion
        {
            get
            {
                object ob = ViewState["SetupdbVersion"];
                if (ob != null)
                    return (int)ob;
                return -2;
            }
            set
            {
                ViewState["SetupdbVersion"] =   value;
            }
        }

        // DB first creation-> special process
        bool isFirstInstall
        {
            get
            {
                object ob = ViewState["isFirstInstall"];
                if (ob != null)
                    return (bool)ob;
                return false;
            }
            set
            {
                ViewState["isFirstInstall"] =   value;
            }
        }

        /// <summary>
		/// This property returns db version.
		/// It does not rely on cached value and always gets the actual value.
		/// </summary>
		private int DatabaseVersion
		{
			get
			{
                return Settings.DatabaseDB.DatabaseVersion;
			}
			set
			{
				//Clear version cache so we are sure we update correctly
                Settings.DatabaseDB.ClearDatabaseVersion();
			}
		}
        
        #endregion properties 

        #region Load event : read history file on first non postback

        /// <summary>
		/// Read the history file on first access and store results in viewstate
		/// </summary>
        protected void Update_Load(object sender, System.EventArgs e)
		{
            InitProgress();
            if (!IsPostBack)
            {
                if (string.IsNullOrEmpty(Config.UpdateUserName))
                {
                    //No login is shown if no user is specified
                    AuthenticationPanel.Visible =   false;
                    InfoPanel.Visible           =   true;
                    UpdatePanel.Visible         =   true;
                }
                else
                {
                    AuthenticationPanel.Visible =   true;
                    InfoPanel.Visible           =   false;
                    UpdatePanel.Visible         =   false;
                }
                try
                {
                    // set and save dbVersion
                    dbVersion                   =   DatabaseVersion;
                    dbNeedsUpdate.Visible       =   false;
                    lblVersion.Text             =   string.Format("DatabaseDB version: {0} - Code version: {1}", dbVersion, PortalSettings.CodeVersion);

                    XmlDocument myDoc           =   new XmlDocument();
                    ArrayList tempScriptsList   =   new ArrayList();
                    totalSteps                  =   0; // one step for each script and each module to install
                    if (dbVersion < PortalSettings.CodeVersion)
                    {
                        if (InstallTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Setup needed DB: {0}, Code: {1}", dbVersion, PortalSettings.CodeVersion), InstallTraceSwitch.Sw.Info);
                        if (dbVersion == -1)
                            isFirstInstall      =   true;
                        // load the history file
                        string myDocPath        =   Server.MapPath(Path2.ApplicationRoot + "/Setup/Scripts/History.xml");
                        myDoc.Load(myDocPath);

                        // get a list of <Release> nodes
                        XmlNodeList releases    =   myDoc.DocumentElement.SelectNodes("Release");

                        // iterate over the <Release> nodes
                        foreach (XmlNode release in releases)
                        {
                            UpdateEntry myUpdate        =   new UpdateEntry();

                            // get the header information
                            // we check for null to avoid exception if any of these nodes are not present
                            if (release.SelectSingleNode("ID") != null)
                                myUpdate.VersionNumber  =   Int32.Parse(release.SelectSingleNode("ID/text()").Value);
                            if (release.SelectSingleNode("Version") != null)
                                myUpdate.Version        =   release.SelectSingleNode("Version/text()").Value;
                            if (release.SelectSingleNode("Date") != null)
                                myUpdate.Date           =   DateTime.Parse(release.SelectSingleNode("Date/text()").Value, CultureInfo.InvariantCulture);

                            // Should we apply this patch
                            if (dbVersion < myUpdate.VersionNumber)
                            {
                                if (InstallTraceSwitch.Sw.TraceVerbose)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Detected version to apply: {0}", myUpdate.Version), InstallTraceSwitch.Sw.Info);

                                myUpdate.Apply          =   true;

                                // get a list of <Sql> nodes
                                XmlNodeList sqlProcs    =   release.SelectNodes("Scripts/Sql");
                                if (InstallTraceSwitch.Sw.TraceVerbose)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Slq scripts count: {0}", sqlProcs.Count), InstallTraceSwitch.Sw.Info);

                                // iterate over the <Sql> Nodes (in original document order)
                                foreach (XmlNode sqlProc0 in sqlProcs)
                                {
                                    XmlElement sqlProc  =   (XmlElement)sqlProc0;
                                    if (InstallTraceSwitch.Sw.TraceVerbose)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Slq script name: {0}, HasAttributes: {1}", sqlProc.OuterXml, sqlProc.HasAttributes), InstallTraceSwitch.Sw.Info);
                                    bool transac        =   true;
                                    if (sqlProc.HasAttributes && sqlProc.HasAttribute("NoTransaction") && bool.Parse(sqlProc.Attributes["NoTransaction"].Value))
                                        transac         =   false;
                                    myUpdate.Transacs.Add(transac);
                                    //and build an ArrayList of the scripts... 
                                    myUpdate.SqlScripts.Add(sqlProc.InnerText);
                                    totalSteps++;
                                    if (InstallTraceSwitch.Sw.TraceVerbose)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Detected sql script to run: {0} transaction: {1}", sqlProc.InnerText, transac), InstallTraceSwitch.Sw.Info);
                                }
                                // get a list of <Installer> nodes
                                XmlNodeList installers  =   release.SelectNodes("Modules/Installer/text()");

                                // iterate over the <Installer> Nodes (in original document order)
                                foreach (XmlNode installer in installers)
                                {
                                    //and build an ArrayList of the scripts... 
                                    myUpdate.Modules.Add(installer.Value);
                                    totalSteps++;
                                    if (InstallTraceSwitch.Sw.TraceVerbose)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Detected module to install: {0}", installer.Value), InstallTraceSwitch.Sw.Info);
                                }
                                tempScriptsList.Add(myUpdate);
                            }
                        }
                        if (InstallTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load Found: {0} scripts to Apply", tempScriptsList.Count), InstallTraceSwitch.Sw.Info);

                        // If we have some version to apply...
                        if (tempScriptsList.Count > 0)
                        {
                            UpdateEntry[] wscriptsList  =   (UpdateEntry[])tempScriptsList.ToArray(typeof(UpdateEntry));

                            //Versions are sorted by version number
                            Array.Sort(wscriptsList);
                            // save in viewState
                            scriptsList                 =   wscriptsList;

                            //Create a flat version for binding
                            int currentVersion          =   0;
                            ArrayList databindList      =   new ArrayList();
                            foreach (UpdateEntry myUpdate in wscriptsList)
                            {
                                if (myUpdate.Apply)
                                {
                                    if (InstallTraceSwitch.Sw.TraceVerbose)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load need to Apply: {0}, SqlScripts.Count: {1}, Transacs.Count: {2}", myUpdate.VersionNumber, myUpdate.SqlScripts.Count, myUpdate.Transacs.Count), InstallTraceSwitch.Sw.Info);
                                    if (currentVersion != myUpdate.VersionNumber)
                                    {
                                        databindList.Add("Version: " + myUpdate.VersionNumber);
                                        currentVersion  =   myUpdate.VersionNumber;
                                    }
                                    for (int i = 0; i < myUpdate.SqlScripts.Count; i++)
                                    {
                                        string sqlProc  =   (string)myUpdate.SqlScripts[i];
                                        bool transac    =   (bool)myUpdate.Transacs[i];
                                        if (InstallTraceSwitch.Sw.TraceVerbose)
                                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load  Script: {0}, {1} ", sqlProc, transac ? "Transaction" : string.Empty), InstallTraceSwitch.Sw.Info);
                                        if (sqlProc.Length > 0)
                                            databindList.Add(string.Format("-- Script: {0}, {1} ", sqlProc, transac ? "Transaction" : string.Empty));
                                    }

                                    foreach (string moduleInstaller in myUpdate.Modules)
                                    {
                                        if (InstallTraceSwitch.Sw.TraceVerbose)
                                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load  moduleInstaller: {0}", moduleInstaller), InstallTraceSwitch.Sw.Info);
                                        if (moduleInstaller.Length > 0)
                                            databindList.Add(string.Format("-- Module: {0}",moduleInstaller));
                                    }
                                }
                            }

                            if (InstallTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Update_Load databindList.Count: {0}", databindList.Count), InstallTraceSwitch.Sw.Info);
                            if (databindList.Count > 0)
                            {
                                dlScripts.DataSource        =   databindList; //we bind a simple list
                                dlScripts.DataBind();
                                dbNeedsUpdate.Visible       =   true;
                                dbNoUpdate.Visible          =   false;
                            }
                            if ( isFirstInstall )
                                totalSteps                  +=  4;

                        }
                        else
                        {
                            // We need an history file Ok, to avoid looping we force a code Exception
                            if (dbVersion < PortalSettings.CodeVersion)
                            {
                                if (InstallTraceSwitch.Sw.TraceError)
                                    Trace2.WriteLine("[E]Update Update_Load Setup update needed and no module to install.", InstallTraceSwitch.Sw.Info);
                                throw new CodeVersionException(lblVersion.Text);
                            }
                        }
                    }
                }
                catch (CodeVersionException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if (InstallTraceSwitch.Sw.TraceError)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update Update_Load ex: {0}", ex), InstallTraceSwitch.Sw.Info);
                    throw;
                }
            }
        }

        #endregion Load handler: read history file on first non postback

        #region Do the update

        void UpdateDatabaseCommand_Click(object sender, ImageClickEventArgs e)
		{
            StartProgress();
            try
            {
			    ArrayList errors			            =   new ArrayList();
			    ArrayList messages			            =   new ArrayList();

                if (InstallTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click scriptsList.Count: {0}, isFirstInstall: {1}.", scriptsList.GetLength(0),isFirstInstall),InstallTraceSwitch.Sw.Info);
                installCount                            =   0;
			    foreach( UpdateEntry myUpdate in scriptsList )
			    {
                    // Version check (a script may update more than one version at once)
                    if ( myUpdate.Apply && myUpdate.VersionNumber >= dbVersion && dbVersion <= PortalSettings.CodeVersion )
				    {
                        bool fatalErr                   =   false;
					    // applying sqlProcs
                        for (int i=0; i <  myUpdate.SqlScripts.Count && !fatalErr ; i++ )
                        {
                            string sqlProc              =   (string)myUpdate.SqlScripts[i];
                            string title    =   string.Format("Release: {0} / {1} script: {2}",myUpdate.VersionNumber,myUpdate.Version,sqlProc);
                            SetUpdateProgress(title,installCount++);
                            bool transac                =   (bool)myUpdate.Transacs[i];
                            string currentScriptName    =   Server.MapPath(System.IO.Path.Combine(Path2.ApplicationRoot + "/Setup/Scripts/", sqlProc));
                            if (InstallTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click CODE: {0}  - DB: {1} - CURR: {2} - Applying: {3}", 
                                    new object[] { PortalSettings.CodeVersion, dbVersion, myUpdate.VersionNumber, currentScriptName }),InstallTraceSwitch.Sw.Info);
                            DBHelper execScript         =   new AddonNice.Helpers.DBHelper();
                            try
                            {
                                execScript.ExecuteScript(currentScriptName, transac);
                            }
                            catch (Exception ex)
                            {
                                if (InstallTraceSwitch.Sw.TraceError)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update UpdateDatabaseCommand_Click installing module: {0}, ex: {1}", currentScriptName, ex),InstallTraceSwitch.Sw.Info);
                                fatalErr                =   true;
                            }
                            finally
                            {
                                if (execScript.errors.Count > 0 )
                                    errors.AddRange(execScript.errors);
                            }
                        }
                        Hashtable instalTb              =   new Hashtable();
					    //Installing modules
                        if (!fatalErr )
					        foreach (string moduleInstaller in myUpdate.Modules)
					        {
                                string title    =   string.Format("Release: {0} / {1} module: {2}",myUpdate.VersionNumber,myUpdate.Version,moduleInstaller);
                                SetUpdateProgress(title,installCount++);
                                string currentModuleInstaller = Server.MapPath(System.IO.Path.Combine(Path2.ApplicationRoot + "/", moduleInstaller));
						        if (InstallTraceSwitch.Sw.TraceVerbose)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click installing module: {0}",currentModuleInstaller),InstallTraceSwitch.Sw.Info);
						        try
						        { 
							        ModuleInstall.InstallGroup(instalTb,Wrapper,currentModuleInstaller, true,null);
						        }
						        catch (Exception ex)
						        {
							        if (InstallTraceSwitch.Sw.TraceError)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update UpdateDatabaseCommand_Click installing module: {0}, ex :{1}",currentModuleInstaller, ex),InstallTraceSwitch.Sw.Info);
							        errors.Add(ex.Message);
						        }
					        }

					    // Display errors if any
					    if (errors.Count > 0)
					    {
						    string currentError		=	myUpdate.Version;
						    errors.Insert(0, "<p>" + currentError + "</p>");
						    if (InstallTraceSwitch.Sw.TraceError)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update UpdateDatabaseCommand_Click Version: {0}, completed with errors: {1}",myUpdate.Version, currentError),InstallTraceSwitch.Sw.Info);
						    break;
					    }
					    else
					    {
                            string title    =   "Updating DB Version";
                            SetUpdateProgress(title,installCount);
						    //Update db with version
						    string versionUpdater   =   string.Format("INSERT INTO [dbo].[adn_Versions] ([Release],[Version],[ReleaseDate]) VALUES('{0}','{1}', CONVERT(datetime, '{2}/{3}/{4}', 101))",
                                new object[]{myUpdate.VersionNumber, myUpdate.Version,myUpdate.Date.Month, myUpdate.Date.Day,myUpdate.Date.Year});
						    AddonNice.Helpers.DBHelper.ExeSQL(versionUpdater);
                            // Reset the database version
                            DatabaseVersion         =   myUpdate.VersionNumber;
                            if (InstallTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click Version: {0}, applied successfully", myUpdate.Version),InstallTraceSwitch.Sw.Info);
					    }
				    }
				    else
				    {
					    //Skipped
					    string skippedMessage = string.Format("Skipping: {0} DbVersion ({1}) Codeversion ({2}).",myUpdate.Version,dbVersion,PortalSettings.CodeVersion);
					    messages.Add(skippedMessage);
                        if (InstallTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click CODE: {0}- DB: {1}- CURR: {2} - Skipping: {3} ", new object[] { PortalSettings.CodeVersion, dbVersion, myUpdate.VersionNumber, myUpdate.Version }),InstallTraceSwitch.Sw.Info);
				    }
			    }

                // On first install :
                // - Grant DB Access to Crm roles
                // - Create the Addon Nice Section in SiteMap
                if (isFirstInstall && (errors.Count == 0) )
                {
                    // More space needed, free this label
                    RadProgressArea1.Localization.CurrentFileName   =   string.Empty;
                    string title                                    =   LocalizeHelper.Localize("PORTAL_SETUP_START_WRAPPER","Starting wrapper");
                    SetUpdateProgress(title,installCount++);
                    if (InstallTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( "[V]Update UpdateDatabaseCommand_Click starting wrapper.",InstallTraceSwitch.Sw.Info);
                    CrmInstaller installer                          =   null;
                    try
                    {
                        DataTable TbPortal                          =   new PortalsDB().GetPortalTb(0); // this has been set by init2.2.0.0 sp for default pratl '0'
                        string portalPath                           =   (string)TbPortal.Rows[0]["PortalPath"];
                        string backupCrmPath                        =   Server.MapPath(Path2.WebPathCombine(Path2.ApplicationRoot,Config.PortalsDirectory,portalPath,"/CrmBackup",StStr.DefaultCrmBackupFolder));
                        if ( InstallTraceSwitch.Sw.TraceVerbose )
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click portalPath: '{0}', backupCrmPath: {1}.",portalPath,backupCrmPath),InstallTraceSwitch.Sw.Info);
                        installer                                   =   new CrmInstaller(backupCrmPath,new List<string>(),delegate(string msg,int countInc)
                                                                                                            {
                                                                                                                installCount += countInc;
                                                                                                                SetUpdateProgress(msg,installCount);
                                                                                                            },
                                                                                                            delegate(int newTot,int nVal){ installCount=nVal; SetTotalStepsProgress( newTot, nVal);}
                                                                                                       );
                        // The first Crm Server params have beeen set in web.config by the install proc,
                        DBCrmServer srvObj                          =   new DBCrmServer
                                                                            {
                                                                                FriendlyName        =   string.Format("{0} server, org: {1}",Config.CRMDiscoServer,Config.CRMOrganization),
                                                                                CrmVersion          =   Config.CRMServiceVersion,
			                                                                    Organization        =   Config.CRMOrganization,
                                                                                AuthenticationType  =   Config.CRMAuthenticationType,
                                                                                DiscoServer         =   Config.CRMDiscoServer,
                                                                                DiscoServerPort     =   Config.CRMDiscoserverPort,
			                                                                    Server3             =   Config.CRMServer,
			                                                                    ServiceAccount      =   Config.CRMServiceAccount,
			                                                                    ServicePassword     =   Config.CRMServicePassword,
			                                                                    ServiceDomain       =   Config.CRMServiceDomain,
                                                                                PrivAccount         =   Config.CRMPrivAccount,
                                                                                PrivPassword        =   Config.CRMPrivPassword,
                                                                                PrivDomain          =   Config.CRMPrivDomain,
                                                                                DefaultAccount      =   Config.CRMDefaultAccount,
                                                                                DefaultPassword     =   Config.CRMDefaultAccountPassword,
                                                                                DefaultDomain       =   Config.CRMDefaultAccountDomain,
                                                                                AdminRoleName       =   Config.CRMAdminRole,
                                                                                UsePreAuthenticate  =   Config.CRMUsePreAuthenticate
                                                                                };
                        
                        // Add CrmServer in DB and install all the custom entities
                        installer.CreateCrmServer(srvObj);
                        
                        // Specific to this Crm Server
                        installer.InstallCrmGroupsInDB();
                        
                        // Insert the CrmServer/Portal link in DB, create the Adonnice Menu in CRM for portal '0'
                        installer.InstallPortal(0,true);

                        // Complete any Crm Iframe or Form for CrmServer and portal '0'
                        installer.InstallCrmUI(0,true,true,true);

                        // do a general publish
                        installer.PostInstall();

                        // Add Admin in Users even when not in Form Authentication-> PB does not work under IIS7: Membership.Provider is null
                        if ( Membership.Provider != null )
                        {
                            AddonNiceMembershipProvider p       =   (AddonNiceMembershipProvider)Membership.Provider;
                            if ( p != null ) // Pb IIS8
                            {
                                try
                                {
                                    p.PortalID                  =   0;
                                    MembershipUser user         =   p.CreateAdmin();
                                    if ( InstallTraceSwitch.Sw.TraceVerbose )
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update UpdateDatabaseCommand_Click CreateAdmin user: '{0}'",(user != null) ? user.UserName:"Null"),InstallTraceSwitch.Sw.Info);
                                }
		                        catch (Exception exp)
		                        {
			                        if (InstallTraceSwitch.Sw.TraceError)
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update UpdateDatabaseCommand_Click Admin User ex : {0}",exp),InstallTraceSwitch.Sw.Info);
		                        }
                            }
                        }
                    }
			        catch (Exception ex)
			        {
				        if (InstallTraceSwitch.Sw.TraceError)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Update UpdateDatabaseCommand_Click wrapper related operation ex: {0}",ex),InstallTraceSwitch.Sw.Info);
				        if ( ( installer != null ) && !string.IsNullOrEmpty(installer.lastError) )
                             errors.Add(installer.lastError);
                        else errors.Add(ex.Message);
			        }
                }

			    dbUpdateResult.Visible			    =   true;
			    dbNeedsUpdate.Visible				=	false;
			    Status.Visible						=	true;
			    // hides update database button
			    UpdateDatabaseCommand.Visible		=	false;
			    // and row, if necessary user will retry from scratch
			    UpdateDatabaseRow.Visible			=	false;
    			
			    if (messages.Count > 0) // warnings non blocking
			    {
				    dlMessages.DataSource			=   messages;
				    dlMessages.DataBind();
				    dlMessages.Visible				=   true;
				    dlMessages.ForeColor			=   System.Drawing.Color.Green;
				    dbUpdateResult.Visible			=   true;
				    dbUpdateResult.Visible			=   true;
			    }

			    if (errors.Count > 0) // errors blocking
			    {
                    lblStatus.Text                  =   LocalizeHelper.Localize("PORTAL_SETUP_DATABASE_UPDATE_ERROR","Error in install script");
				    dlErrors.DataSource				=   errors;
				    dlErrors.DataBind();
				    dlErrors.Visible				=   true;
				    FinishButton.Visible            =   false;
			    }
            }
            catch(CancelProgressException )
            {
                if (InstallTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( "[V]Update UpdateDatabaseCommand_Click install cancelled by user.",InstallTraceSwitch.Sw.Info);
                lblStatus.Text                      =   LocalizeHelper.Localize("PROGRESS_CANCELLED","Install cancelled by user");
            }
            finally
            {
                EndProgress();
            }
        }
        #endregion Do the update

        #region Alternate buttons click management

        void FinishButton_Click(object sender, ImageClickEventArgs e)
		{
			if (InstallTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]Update FinishButton clicked.",InstallTraceSwitch.Sw.Info);
			Response.Redirect("~/"+Config.DefaultModulesPage);
		}
		
		void authenticateUser_Click(object sender, ImageClickEventArgs e)
		{
			string providedUser					=   string.Empty;
			string providedPassword				=   string.Empty;

			if ( !string.IsNullOrEmpty(Config.UpdateUserName) )
                providedUser					=   Config.UpdateUserName;

			if ( !string.IsNullOrEmpty(Config.UpdatePassword) )
				providedPassword				=   Config.UpdatePassword;

			if((providedUser.ToLower() == updateUsername.Text.ToLower()) && (providedPassword == updatePassword.Text))
			{
				AuthenticationPanel.Visible		=   false;
				UpdatePanel.Visible				=   true;
				if (InstallTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Someone has accessed to the setup / update page. User IP: {0},  Username Entered: '{1}'",HttpContext.Current.Request.UserHostAddress,updateUsername.Text),InstallTraceSwitch.Sw.Info);
			}
			else
			{
				loginError.Visible				=   true;
				if (InstallTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update Someone has incorrectly tried to log into the setup / update page. User IP: {0},  Username Entered: '{1}', Password Entered: '{2}'",HttpContext.Current.Request.UserHostAddress,updateUsername.Text,updatePassword.Text),InstallTraceSwitch.Sw.Info);
			}
		}

        #endregion Alternate buttons click management

        #region Install progress management

        /*
            PrimaryTotal The maximum value of the primary progress indicators. By default, RadProgressArea displays the request size. 
            PrimaryValue The current value of the primary progress indicators. By default, RadProgressArea displays the uploaded bytes count. 
            PrimaryPercent The current value of the primary progress, expressed as a percentage of PrimaryTotal. 
            SecondaryTotal The maximum value of the secondary progress indicators. By default, RadProgressArea displays the total number of files. 
            SecondaryValue The current value of the secondary progress indicators. By default, RadProgressArea displays the number of files already uploaded. 
            SecondaryPercent The current value of the secondary progress, expressed as a percentage of SecondaryTotal. 
            CurrentOperationText The description of the current operation. By default, RadProgressArea displays the name of the currently uploading file. 
            TimeEstimated The estimated time until the operation completes. 
            TimeElapsed The time that has elapsed from the beginning of the operation. 
            Speed The speed of the process. By default, RadProgressArea displays the upload speed.
         */
        void InitProgress()
        {
            RadProgressArea1.Localization.UploadedFiles     =   LocalizeHelper.Localize("PROGRESS_COMPLETED_STEPS","Completed Steps: ");
            RadProgressArea1.Localization.CurrentFileName   =   LocalizeHelper.Localize("PROGRESS_STEP","Step: ");
            RadProgressArea1.Localization.TotalFiles        =   LocalizeHelper.Localize("PROGRESS_TOTAL_STEPS","Total Steps: ");
        }

        void StartProgress()
        {
            RadProgressContext context      =   RadProgressContext.Current;
            //context.PrimaryTotal            =   "100";
            //context.PrimaryValue            =   "0";
            //context.PrimaryPercent          =   "0";
            context.SecondaryTotal          =   totalSteps;
            context.SecondaryValue          =   "0";
            context.SecondaryPercent        =   "0";
            context.CurrentOperationText    =   "Start";
        }

        void EndProgress()
        {
            RadProgressContext.Current.OperationComplete = true;
        }

        /// <summary>
        /// When the total number of items change, call this to reset progress display
        /// </summary>
        public void SetTotalStepsProgress(int newTot,int secVal)
        {
            if ( newTot == 0 )
                return;
            totalSteps                      =   newTot;
            RadProgressContext progress     =   RadProgressContext.Current;
            progress.SecondaryTotal         =   totalSteps;
            progress.SecondaryValue         =   secVal.ToString();
            progress.SecondaryPercent       =   (secVal*100/totalSteps).ToString();
        }

        /// <summary>
        /// Used to change the progress display with a new value and text
        /// </summary>
        public void SetUpdateProgress(string text,int secVal)
        {
            RadProgressContext progress     =   RadProgressContext.Current;
            //progress.PrimaryValue           =   primVal.ToString();
            //progress.PrimaryPercent         =   primVal.ToString();
            progress.SecondaryValue         =   secVal.ToString();
            progress.SecondaryPercent       =   (secVal*100/totalSteps).ToString();

            progress.CurrentOperationText   =   text;

            //Cancel button was clicked or the browser was closed, so stop processing
            if (!Response.IsClientConnected)
            {
                if (InstallTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Update SetUpdateProgress Cancel clicked text: {0}, secVal: {1}.", text,secVal),InstallTraceSwitch.Sw.Info);
                throw new CancelProgressException();
            };
        }

        #endregion Install progress management

		#region Std overrides

		protected override void OnPreInit(EventArgs e)
		{
			// we translate skins according to locals
			try
			{
				string strloc                   =   Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
				authenticateUser.SkinID         =   "setuplogin_" + strloc;
				FinishButton.SkinID             =   "setupfinish_" + strloc;
				FinishButton2.SkinID            =   "setupfinish_" + strloc;
				UpdateDatabaseCommand.SkinID    =   "setupnext_" + strloc;
			}
			catch
			{
				string strloc                   = "en";
				authenticateUser.SkinID         = "setuplogin_" + strloc;
				FinishButton.SkinID             = "setupfinish_" + strloc;
				FinishButton2.SkinID            = "setupfinish_" + strloc;
				UpdateDatabaseCommand.SkinID    = "setupnext_" + strloc;
			}
			base.OnPreInit(e);
		}

        override protected void OnInit(EventArgs e)
		{
			//always modified
			Response.AddHeader("Last-Modified", DateTime.Now.ToUniversalTime().ToString() + " GMT");
			//HTTP/1.1 
			Response.AddHeader("Cache-Control", "no-cache, must-revalidate");
			//HTTP/1.0 
			Response.AddHeader("Pragma", "no-cache");
			Response.Expires = -100;
			InitializeComponent();
			base.OnInit(e);
		}
		
		private void InitializeComponent()
		{
            this.Load							+=	new System.EventHandler(this.Update_Load);
			this.UpdateDatabaseCommand.Click	+=	new ImageClickEventHandler(UpdateDatabaseCommand_Click);
			this.FinishButton.Click				+=	new ImageClickEventHandler(FinishButton_Click);
			this.FinishButton2.Click			+=	new ImageClickEventHandler(FinishButton_Click);
			this.authenticateUser.Click += new ImageClickEventHandler(authenticateUser_Click);
		}
		
		#endregion Std overrides

    }
}

